using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Browser;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Navigation;
using Lib.Approval;
using Lib.Helper;
using Lib.Mail;
using MSIACCSL2.ApplicationStateServices;
using MSIACCSL2.BtbElseServices;
using MSIACCSL2.Command;
using MSIACCSL2.InventoryServices;
using MSIACCSL2.ItemServices;
using MSIACCSL2.PalletServices;
using MSIACCSL2.PurchaseOrderServices;
using MSIACCSL2.SatuanServices;
using MSIACCSL2.SupplierServices;
using MSIACCSL2.Views.BTBElse;
using MSIACCSL2.WarehouseServices;
using WcfService1.DTO;
using GetListByCriteriaCompletedEventArgs = MSIACCSL2.BtbElseServices.GetListByCriteriaCompletedEventArgs;
using GetListCompletedEventArgs = MSIACCSL2.BtbElseServices.GetListCompletedEventArgs;
using SaveCompletedEventArgs = MSIACCSL2.BtbElseServices.SaveCompletedEventArgs;
using SendEmailCompletedEventArgs = MSIACCSL2.BtbElseServices.SendEmailCompletedEventArgs;

namespace MSIACCSL2.ViewModels
{
    public class BtbElseViewModel : ViewModelBase
    {
        #region Delegates

        public delegate void Completed(Object param);

        #endregion

        private static Search frmSearch;
        private static string OrderType;
        private static string PropertySort;
        public static Mode mode;
        private static FrmAdd frmAdd;
        public static Completed OnSearchCompleted;
        private static NavigationService _NavigationService;
        private readonly AplicationStateServicesClient ApplicationService;
        private readonly ItemServicesClient ItemClient;
        private readonly PalletServicesClient PalletClient;
        private readonly PurchaseOrderServicesClient PurchaseOrderClient;
        private readonly SatuanServicesClient SatuanClient;
        private readonly SupplierServicesClient SupplierClient;
        private readonly WarehouseServicesClient WarehouseServicesClient;
        private readonly InventoryServices.InventoryServiceClient invClient;
        private readonly ValidationHandler validationHandler;
        private int CurrentPage;
        private bool IsUsed;
        private PurchaseOrderDTO POTemp;
        private ObservableCollection<int> Pages;
        private BtbElseDTO _BtbElse;
        private BtbElseDetailDTO _BtbElseDetailCurrent;
        private PagedCollectionView _BtbElses;
        private bool _IsBusy;
        private bool _IsEnabled;
        private ObservableCollection<ItemDTO> _Items;
        private bool _NoLogfocus;
        private ObservableCollection<PurchaseOrderDTO> _PurchaseOrders;
        private ObservableCollection<SatuanDTO> _SatuanPacks;
        private ObservableCollection<SatuanDTO> _SatuanUnits;
        private ObservableCollection<SupplierDTO> _Suppliers;
        private ObservableCollection<WarehouseDTO> _Warehouses;
        private List<string> _errors;
        private Visibility _messageVisibility;
        private PagedCollectionView _pageSources;
        private BtbElseServicesClient client;
        private Dictionary<string, object> criteria;
        private string expression;


        public BtbElseViewModel()
        {
            WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
            _IsEnabled = true;

            if (!DesignerProperties.IsInDesignTool)
            {
                client = new BtbElseServicesClient();
                SatuanClient = new SatuanServicesClient();
                WarehouseServicesClient = new WarehouseServicesClient();
                invClient = new InventoryServiceClient();
                OnPageChanged = new DelegateCommand(PageIndexChanged, CanPageIndexChanged);
                Save = new DelegateCommand(SaveBtbElse, CanSave);
                New = new DelegateCommand(NewBtbElse, CanNew);
                Unload = new DelegateCommand(Release, CanUnload);
                SearchCommand = new DelegateCommand(SearchBtbElse, CanSearch);
                SearchResultCommand = new DelegateCommand(SearchResult, CanSearchResult);
                CancelCommand = new DelegateCommand(Cancel, CanCancelCommand);
                GetPOCommand = new DelegateCommand(GetPO, CanGetPOCommand);
                validationHandler = new ValidationHandler();
                MessageVisibility = Visibility.Collapsed;
                PurchaseOrderClient = new PurchaseOrderServicesClient();
                SupplierClient = new SupplierServicesClient();
                ItemClient = new ItemServicesClient();
                PalletClient = new PalletServicesClient();
                ApplicationService = new AplicationStateServicesClient();
                LoadDetailfromFileCommand = new DelegateCommand(LoadDetailFromFile, CanLoadDetailFromFile);

                if (mode == Mode.Edit)
                {
                    PrepareEdit();
                }
                else if (mode == Mode.Search)
                {
                    BtbElse = new BtbElseDTO();
                    BtbElse.TglBtb = null;
                    GetPurchaseOrderList();
                    GetSupplierList();
                }
                else if (mode == Mode.Add)
                {
                    PrepareAdd();
                }
                else
                {
                    GetList(1, null);
                }
            }
        }

        public Dictionary<string, ItemDTO> itemDicts { get; set; }
        public WarehouseDTO CurrentWarehouse { get; set; }

        public PagedCollectionView BtbElses
        {
            get { return _BtbElses; }

            private set
            {
                if (BtbElses == value) return;
                _BtbElses = value;
                int i = (CurrentPage*30);
                foreach (object BtbElse in BtbElses)
                {
                    i += 1;

                    ((BtbElseDTO) BtbElse).No = i;
                }
                FirePropertyChanged("BtbElses");
                BtbElses.CollectionChanged += BtbElse_CollectionChanged;
            }
        }

        public PagedCollectionView PageSources
        {
            get { return _pageSources; }
            private set
            {
                if (PageSources == value) return;
                _pageSources = value;
                FirePropertyChanged("PageSources");
            }
        }


        public ObservableCollection<PurchaseOrderDTO> PurchaseOrders
        {
            get { return _PurchaseOrders; }
            private set
            {
                if (PurchaseOrders == value) return;
                _PurchaseOrders = value;
                FirePropertyChanged("PurchaseOrders");
            }
        }


        public ObservableCollection<SupplierDTO> Suppliers
        {
            get { return _Suppliers; }
            private set
            {
                if (Suppliers == value) return;
                _Suppliers = value;
                FirePropertyChanged("Suppliers");
            }
        }


        public bool IsBusy
        {
            get { return _IsBusy; }
            internal set
            {
                _IsBusy = value;
                FirePropertyChanged("IsBusy");
            }
        }


        public long RecordCount { get; set; }

        //Buat binding ke child form waktu mau edit
        public BtbElseDTO BtbElse
        {
            get { return _BtbElse; }
            private set
            {
                if (BtbElse == value) return;
                _BtbElse = value;
                FirePropertyChanged("BtbElse");
            }
        }

        public BtbElseDetailDTO BtbElseDetailCurrent
        {
            get { return _BtbElseDetailCurrent; }
            private set
            {
                if (BtbElseDetailCurrent == value) return;
                _BtbElseDetailCurrent = value;
                FirePropertyChanged("BtbElseDetailCurrent");
            }
        }

        public ObservableCollection<ItemDTO> Items
        {
            get { return _Items; }
            set
            {
                if (Items == value) return;
                _Items = value;
                FirePropertyChanged("Items");
            }
        }

        public ObservableCollection<SatuanDTO> SatuanPacks
        {
            get { return _SatuanPacks; }
            private set
            {
                if (SatuanPacks == value) return;
                _SatuanPacks = value;
                FirePropertyChanged("SatuanPacks");
            }
        }


        public ObservableCollection<SatuanDTO> SatuanUnits
        {
            get { return _SatuanUnits; }
            private set
            {
                if (SatuanUnits == value) return;
                _SatuanUnits = value;
                FirePropertyChanged("SatuanUnits");
            }
        }


        public ObservableCollection<WarehouseDTO> Warehouses
        {
            get { return _Warehouses; }
            private set
            {
                if (Warehouses == value) return;
                _Warehouses = value;
                FirePropertyChanged("Warehouses");
            }
        }

        public bool NoLogFocus
        {
            get { return _NoLogfocus; }
            set
            {
                if (NoLogFocus == value) return;
                _NoLogfocus = value;
                FirePropertyChanged("NoLogFocus");
            }
        }


        public ICommand OnPageChanged { get; set; }
        public ICommand Save { get; set; }
        public ICommand New { get; set; }
        public ICommand Edit { get; set; }
        public ICommand Unload { get; set; }
        public ICommand SearchCommand { get; set; }
        public ICommand SearchResultCommand { get; set; }
        public ICommand CancelCommand { get; set; }
        public ICommand GetPOCommand { get; set; }
        public ICommand PrintCommand { get; set; }
        public ICommand LoadDetailfromFileCommand { get; set; }


        public List<string> Errors
        {
            get { return _errors; }
            private set
            {
                if (Errors == value) return;
                _errors = value;
                FirePropertyChanged("Errors");
            }
        }

        public Visibility MessageVisibility
        {
            get { return _messageVisibility; }
            private set
            {
                if (MessageVisibility == value) return;
                _messageVisibility = value;
                FirePropertyChanged("MessageVisibility");
            }
        }

        public bool IsEnabled
        {
            get { return _IsEnabled; }
            internal set
            {
                _IsEnabled = value;
                FirePropertyChanged("IsEnabled");
            }
        }

        private void PrepareEdit()
        {
            BtbElse = (BtbElseDTO) Navigation.Args;
            GetBtbElse(BtbElse);
            CekTransaksi();
            GetItemList();
        }

        private void PrepareAdd()
        {
            //GetLastNoBtb();
            GetSatuanPackList();
            GetWarehouseList();
            BtbElse = new BtbElseDTO();
            BtbElse.BtbDetails = new ObservableCollection<BtbElseDetailDTO>();
            var BtbElseDetail = new BtbElseDetailDTO();
            BtbElse.BtbDetails.Add(BtbElseDetail);
            GetItemList();
            //CekTransaksi();
        }

        private void GetBtbElse(BtbElseDTO param)
        {
            IsBusy = true;
            client.GetBtbElseCompleted += client_GetBtbElseCompleted;
            client.GetBtbElseAsync(param.NoBtb);
        }

        private void client_GetBtbElseCompleted(object sender, GetBtbElseCompletedEventArgs e)
        {
            client = sender as BtbElseServicesClient;
            client.GetBtbElseCompleted -= client_GetBtbElseCompleted;
            BtbElse = e.Result;
            GetSatuanPackList();
            GetWarehouseList();
            POTemp = BtbElse.PurchaseOrder;
            if (BtbElse.BtbDetails == null)
                BtbElse.BtbDetails = new ObservableCollection<BtbElseDetailDTO>();
            if (BtbElse.BtbDetails.Count == 0)
                BtbElse.BtbDetails.Add(new BtbElseDetailDTO());

            foreach (BtbElseDetailDTO BtbElseDetail in BtbElse.BtbDetails)
            {
                BtbElseDetail.Items = new ObservableCollection<ItemDTO>();
                BtbElseDetail.Items.Add(BtbElseDetail.Item);
            }

            IsBusy = false;
        }


        public void Complete(Object param)
        {
            OnSearchCompleted(param);
        }

        private void BtbElse_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (((PagedCollectionView) sender).SortDescriptions.Count > 0)
            {
                if (((PagedCollectionView) sender).SortDescriptions[0].PropertyName.ToLower() == "no") return;

                PropertySort = ((PagedCollectionView) sender).SortDescriptions[0].PropertyName;
                if (string.IsNullOrEmpty(OrderType))
                {
                    OrderType = "ASC";
                }
                else
                {
                    OrderType = OrderType == "ASC" ? OrderType = "DESC" : OrderType = "ASC";
                }
                GetList(1, PropertySort);
            }
        }


        public void SaveBtbElse(Object btbElse)
        {
            //BtbElse = (BtbElseDTO) btbElse;
            if (BtbElse.BtbDetails.Count == 1)
            {
                //Bila tidak ada yang dipilih di detail maka details harus dihapus
                if (BtbElse.BtbDetails[0].Item == null)
                    BtbElse.BtbDetails.Clear();
            }
            Validate();
            if (Errors.Count > 0) return;
            BtbElse.created_by = GlobalVar.User.UserID;
            BtbElse.modified_by = GlobalVar.User.UserID;
            client.SaveCompleted += client_SaveCompleted;

            IsBusy = true;
            client.SaveAsync(BtbElse, mode);
        }

        private void client_SaveCompleted(object sender, SaveCompletedEventArgs e)
        {
            client.SaveCompleted -= client_SaveCompleted;
            IsBusy = false;
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
                return;
            }
            
            mode = (Mode) e.UserState;
            if (e.Result)
            {
                ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.Navigate(new Uri("/BtbElse/Index", UriKind.Relative));
            }
            else
            {
                MessageBox.Show("Simpan Gagal!");
            }
        }


        public void GetList(int? page, string sortProp)
        {
            IsBusy = true;
            client.GetListCompleted += client_GetListCompleted;
            client.GetListAsync(page ?? 1, sortProp, OrderType);
        }

        private void client_GetListCompleted(object sender, GetListCompletedEventArgs e)
        {
            RecordCount = e.recordCount;
            if (PageSources == null) CreatePageNumber();
            client.GetListCompleted -= client_GetListCompleted;
            BtbElses = new PagedCollectionView(e.Result);
            IsBusy = false;
            Complete(this);
        }


        private void NewBtbElse(Object param)
        {
            mode = Mode.Add;
            Navigation.MyNavigation = (NavigationService) param;
            Navigation.MyNavigation.Navigate(new Uri("/BtbElse/frmAdd", UriKind.Relative));
        }


        private void SearchBtbElse(Object param)
        {
            mode = Mode.Search;
            frmSearch = new Search();
            frmSearch.Show();
        }


        private void SearchResult(Object param)
        {
            criteria = new Dictionary<string, object>();

            foreach (PropertyInfo prop in BtbElse.GetType().GetProperties())
            {
                if (prop.PropertyType == typeof (Decimal))
                {
                    if ((Decimal) prop.GetValue(BtbElse, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Int32))
                {
                    if ((Int32) prop.GetValue(BtbElse, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Int64))
                {
                    if ((Int64) prop.GetValue(BtbElse, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (Double))
                {
                    if ((Double) prop.GetValue(BtbElse, null) == 0) continue;
                }
                if (prop.PropertyType == typeof (String))
                {
                    if (String.IsNullOrEmpty((String) prop.GetValue(BtbElse, null))) continue;
                }
                if (prop.PropertyType == typeof (DateTime))
                {
                    if (prop.GetValue(BtbElse, null).ToString().Contains("0001")) continue;
                }
                if (prop.GetValue(BtbElse, null) == null) continue;
                if (prop.PropertyType.Name == "No") continue;

                if (prop.PropertyType.Name.ToLower().Contains("dto"))
                {
                    foreach (PropertyInfo propertyInfo in prop.GetValue(BtbElse, null).GetType().GetProperties()
                        )
                    {
                        if (propertyInfo.Name.ToLower().Contains("id") || propertyInfo.Name.ToLower().Contains("kode") ||
                            propertyInfo.Name.ToLower().Contains("serial") ||
                            propertyInfo.Name.ToLower().Contains("code"))
                        {
                            criteria.Add(prop.Name, propertyInfo.GetValue(prop.GetValue(BtbElse, null), null));
                            break;
                        }
                    }
                }
                else
                {
                    criteria.Add(prop.Name, prop.GetValue(BtbElse, null));
                }
            }

            expression = string.Empty;
            if (frmSearch.rblOr.IsChecked ?? false) expression = "OR";
            else expression = "AND";
            BtbElseSearch(criteria, expression, 1);
        }

        private void BtbElseSearch(Dictionary<String, Object> criteria, string expression, int page)
        {
            if (criteria != null) if (criteria.ContainsKey("Status")) criteria.Remove("Status");
            frmSearch.DialogResult = true;
            IsBusy = true;
            Complete(this);
            client.GetListByCriteriaCompleted += client_GetListByCriteriaCompleted;
            client.GetListByCriteriaAsync(criteria, expression, page, criteria);
        }

        private void client_GetListByCriteriaCompleted(object sender, GetListByCriteriaCompletedEventArgs e)
        {
            client.GetListByCriteriaCompleted -= client_GetListByCriteriaCompleted;
            BtbElses = new PagedCollectionView(e.Result);
            if (RecordCount != e.recordCount)
            {
                RecordCount = e.recordCount;
                CreatePageNumber();
            }
            IsBusy = false;
            criteria = (Dictionary<String, Object>) e.UserState;
        }


        private void GetPurchaseOrderList()
        {
            PurchaseOrderClient.GetAllPurchaseOrderCompleted += PurchaseOrderClient_GetAllPurchaseOrderCompleted;
            PurchaseOrderClient.GetAllPurchaseOrderAsync();
        }

        private void PurchaseOrderClient_GetAllPurchaseOrderCompleted(object sender,
                                                                      GetAllPurchaseOrderCompletedEventArgs e)
        {
            PurchaseOrderClient.GetAllPurchaseOrderCompleted -= PurchaseOrderClient_GetAllPurchaseOrderCompleted;
            e.Result.Insert(0, new PurchaseOrderDTO {PONumber = "--Pilih--"});
            PurchaseOrders = e.Result;
            //Mapping PO Detail
            foreach (PurchaseOrderDTO purchaseOrder in PurchaseOrders)
            {
                purchaseOrder.PurchaseOrderDetails = new ObservableCollection<PurchaseOrderDetailDTO>();
                PurchaseOrderDTO PO =
                    e.Result.FirstOrDefault(x => x.PONumber == purchaseOrder.PONumber);

                foreach (PurchaseOrderDetailDTO PODetail in PO.PurchaseOrderDetails)
                    purchaseOrder.PurchaseOrderDetails.Add(
                        PODetail);
            }

            if (BtbElse != null)
            {
                if (BtbElse.PurchaseOrder == null) return;
                BtbElse.PurchaseOrder =
                    PurchaseOrders.FirstOrDefault(s => s.PONumber == BtbElse.PurchaseOrder.PONumber);
                BtbElse.PurchaseOrder = POTemp;
            }
        }

        private void GetSupplierList()
        {
            SupplierClient.GetAllSupplierCompleted += SupplierClient_GetAllSupplierCompleted;
            SupplierClient.GetAllSupplierAsync();
        }

        private void SupplierClient_GetAllSupplierCompleted(object sender, GetAllSupplierCompletedEventArgs e)
        {
            SupplierClient.GetAllSupplierCompleted -= SupplierClient_GetAllSupplierCompleted;
            Suppliers = e.Result;

            if (BtbElse != null)
            {
                if (BtbElse.Supplier == null) return;
                BtbElse.Supplier =
                    Suppliers.FirstOrDefault(s => s.SupplierId == BtbElse.Supplier.SupplierId);
            }
        }


        private void CreatePageNumber()
        {
            Pages = new ObservableCollection<int>();
            for (int i = 0; i < RecordCount; i++)
            {
                Pages.Add(i);
            }
            PageSources = new PagedCollectionView(Pages);
        }


        private void PageIndexChanged(Object pageIndex)
        {
            //Jika Pertama kali jangan di Getlagi
            BtbElse = null;
            if (BtbElses != null && CurrentPage != (int) pageIndex)
            {
                CurrentPage = (int) pageIndex;
                if (mode == Mode.Search)
                    BtbElseSearch(criteria, expression, (int) pageIndex + 1);
                else if (String.IsNullOrEmpty(PropertySort))
                    GetList((int) pageIndex + 1, null);
                else GetList((int) pageIndex + 1, PropertySort);
            }
        }


        public bool CanPageIndexChanged(Object param)
        {
            return true;
        }


        public bool CanSave(Object param)
        {
            return true;
        }


        public bool CanNew(Object param)
        {
            return true;
        }

        public bool CanEdit(Object param)
        {
            return true;
        }


        public bool CanUnload(Object param)
        {
            return true;
        }


        public bool CanSearch(Object param)
        {
            return true;
        }

        public bool CanSearchResult(Object param)
        {
            return true;
        }

        public bool CanCancelCommand(Object param)
        {
            return true;
        }

        public bool CanGetPOCommand(Object param)
        {
            return true;
        }

        public bool CanPrintCommand(Object param)
        {
            return true;
        }


        public void Release(Object param)
        {
            param = null;
            BtbElse = null;
            OrderType = null;
            PropertySort = null;
            mode = Mode.Idle;
        }


        public void Refresh()
        {
            if (BtbElses == null)
                GetList(1, null);
            else
                Complete(this);
        }


        public void Validate(string error = null)
        {
            Errors = new List<string>();
            //if (string.IsNullOrEmpty(BtbElse.NoBtb))
            //    Errors.Add("Nomor BtbElse tidak boleh kosong");
            if (BtbElse.BtbDetails.Count < 1)
                Errors.Add("BTb Detail harus diisi!");

            if (!string.IsNullOrEmpty(error))
                Errors.Add(error);

            if (Errors.Count > 0)
            {
                MessageVisibility = Visibility.Visible;
            }
            else
            {
                MessageVisibility = Visibility.Collapsed;
            }
        }

        public void Cancel(Object param)
        {
            MessageBoxResult res = MessageBox.Show("Are You Sure Want to Cancel ?", "Confirmation",
                                                   MessageBoxButton.OKCancel);
            if (res == MessageBoxResult.OK)
            {
                ClearTransaksi(mode);
                mode = Mode.Idle;
                Navigation.MyNavigation.GoBack();
            }
        }

        private void GetLastNoBtb()
        {
            client = new BtbElseServicesClient();
            client.GetLastBtbElseNoCompleted += client_GetLastBtbElseNoCompleted;
            client.GetLastBtbElseNoAsync();
        }

        private void client_GetLastBtbElseNoCompleted(object sender, GetLastBtbElseNoCompletedEventArgs e)
        {
            client.GetLastBtbElseNoCompleted -= client_GetLastBtbElseNoCompleted;
            //string res = e.Result;
            //string formatSO = "0000";
            //string kodeSO;
            //if (e.Result.Length <= 4)
            //{
            //    res = formatSO;
            //    kodeSO = e.Result;
            //}
            //else
            //{
            //    res = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[2];
            //    kodeSO = e.Result.Split(new[] {"/"}, StringSplitOptions.RemoveEmptyEntries)[0];
            //}
            //string soNum = formatSO.Substring(0, formatSO.Length - (int.Parse(res) + 1).ToString().Length) +
            //               (int.Parse(res) + 1);

            //BtbElse.NoBtb = kodeSO + "/" + DateTime.Now.Year + "/" + soNum;
            BtbElse.NoBtb = e.Result;
        }


        public void GetPO(Object param)
        {
            var PO = param as PurchaseOrderDTO;
            if (PO == null || PO.PONumber.ToLower().Contains("pilih")) return;
            string PONo = ((PurchaseOrderDTO) param).PONumber;
            PurchaseOrderClient.GetPurchaseOrderCompleted += PurchaseOrderClient_GetPurchaseOrderCompleted;
            PurchaseOrderClient.GetPurchaseOrderAsync(PONo);
        }

        private void PurchaseOrderClient_GetPurchaseOrderCompleted(object sender, GetPurchaseOrderCompletedEventArgs e)
        {
            BtbElse.PurchaseOrder = e.Result;
            PurchaseOrderClient.GetPurchaseOrderCompleted -= PurchaseOrderClient_GetPurchaseOrderCompleted;
            if (BtbElse != null)
                BtbElse.Supplier =
                    Suppliers.FirstOrDefault(
                        x =>
                        x.SupplierId ==
                        e.Result.Supplier.SupplierId);
        }

        public void GetItemByName(Object param)
        {
            if (param.GetType() == typeof (BtbElseDetailDTO))
            {
                BtbElseDetailCurrent = param as BtbElseDetailDTO;
                ItemClient.GetItemByNameCompleted += ItemClient_GetItemByNameCompleted;
                ItemClient.GetItemByNameAsync(BtbElseDetailCurrent.Item.ItemName);
            }
            else
            {
                ItemClient.GetItemByNameCompleted += ItemClient_GetItemByNameCompleted;
                ItemClient.GetItemByNameAsync(param.ToString());
            }
        }

        private void ItemClient_GetItemByNameCompleted(object sender, GetItemByNameCompletedEventArgs e)
        {
            ItemClient.GetItemByNameCompleted -= ItemClient_GetItemByNameCompleted;
            Items = e.Result;
        }

        public void GetPalletByWarehouse(Object param)
        {
            var BtbElseDetail = param as BtbElseDetailDTO;
            PalletClient.GetPalletByWarehouseCompleted += PalletClient_GetPalletByWarehouseCompleted;
            PalletClient.GetPalletByWarehouseAsync(BtbElseDetail.Warehouse, BtbElseDetail);
        }

        private void PalletClient_GetPalletByWarehouseCompleted(object sender, GetPalletByWarehouseCompletedEventArgs e)
        {
            var BtbElseDetail = e.UserState as BtbElseDetailDTO;
            string Pallet = BtbElseDetail.KodePallet;
            BtbElseDetail.Pallets = e.Result;
            BtbElseDetail.KodePallet = Pallet;
        }

        public void Print(Object param)
        {
            Navigation.MyNavigation.Navigate(new Uri("/BtbElse/PrintPreviewBtbElse", UriKind.Relative));
            Navigation.Args = param;
        }

        public void GetSatuanPackList()
        {
            SatuanClient.GetAllSatuanCompleted += SatuanClient_GetAllSatuanCompleted;
            SatuanClient.GetAllSatuanAsync();
        }

        private void SatuanClient_GetAllSatuanCompleted(object sender, GetAllSatuanCompletedEventArgs e)
        {
            SatuanClient.GetAllSatuanCompleted -= SatuanClient_GetAllSatuanCompleted;
            SatuanPacks = e.Result;
            SatuanUnits = e.Result;
            RefreshSatuan();
        }

        public void GetWarehouseList()
        {
            WarehouseServicesClient.GetAllWarehouseCompleted += WarehouseServicesClient_GetAllWarehouseCompleted;
            WarehouseServicesClient.GetAllWarehouseAsync();
        }

        private void WarehouseServicesClient_GetAllWarehouseCompleted(object sender, GetAllWarehouseCompletedEventArgs e)
        {
            WarehouseServicesClient.GetAllWarehouseCompleted -= WarehouseServicesClient_GetAllWarehouseCompleted;
            Warehouses = e.Result;
            RefreshWarehouse();
        }


        private void RefreshWarehouse()
        {
            if (BtbElse != null)
                foreach (BtbElseDetailDTO BtbElseDetail in BtbElse.BtbDetails)
                {
                    BtbElseDetail.Warehouses = Warehouses;
                    if (BtbElseDetail.Warehouse != null)
                    {
                        BtbElseDetail.Warehouse =
                            Warehouses.FirstOrDefault(s => s.KodeWarehouse == BtbElseDetail.Warehouse.KodeWarehouse);
                    }
                }
        }

        private void RefreshSatuan()
        {
            if (BtbElse != null)
                foreach (BtbElseDetailDTO BtbElseDetail in BtbElse.BtbDetails)
                {
                    BtbElseDetail.SatuanPacks = SatuanPacks;
                    BtbElseDetail.SatuanUnits = SatuanPacks;
                    if (BtbElseDetail.SatuanPack != null)
                    {
                        BtbElseDetail.SatuanPack =
                            SatuanPacks.FirstOrDefault(s => s.KodeSatuan == BtbElseDetail.SatuanPack.KodeSatuan);
                        BtbElseDetail.SatuanUnit =
                            SatuanUnits.FirstOrDefault(s => s.KodeSatuan == BtbElseDetail.SatuanUnit.KodeSatuan);
                    }
                }
        }

        public void SendEmail(Object param)
        {
            var chooseDestination = new ChooseDestination();
            chooseDestination.Show();
            EventAggregator.RegisterMessage("SendDestination", (x) =>
                                                                   {
                                                                       IsBusy = true;
                                                                       client.ChannelFactory.Closed +=
                                                                           ChannelFactory_Closed;
                                                                       client.ChannelFactory.Faulted +=
                                                                           ChannelFactory_Faulted;
                                                                       client.InnerChannel.Closed += InnerChannel_Closed;
                                                                       client.SendEmailCompleted +=
                                                                           client_SendEmailCompleted;
                                                                       client.SendEmailAsync(param as BtbElseDTO,
                                                                                             (x as WarehouseDTO).
                                                                                                 EmailFolder);
                                                                   });
        }

        private void InnerChannel_Closed(object sender, EventArgs e)
        {
            MessageBox.Show("Inner Channel Close");
        }

        private void ChannelFactory_Faulted(object sender, EventArgs e)
        {
            MessageBox.Show("Channel Fault");
        }

        private void ChannelFactory_Closed(object sender, EventArgs e)
        {
            MessageBox.Show("Channel Close!");
        }

        private void client_SendEmailCompleted(object sender, SendEmailCompletedEventArgs e)
        {
            IsBusy = false;
            client.SendEmailCompleted -= client_SendEmailCompleted;
            MessageBox.Show(e.Error != null ? e.Error.Message : "Pengiriman Selesai");
        }


        public void CekTransaksi()
        {
            ApplicationService.IsTransactionUsedCompleted += ApplicationService_IsTransactionUsedCompleted;
            if (string.IsNullOrEmpty(BtbElse.NoBtb))
            {
                ApplicationService.IsTransactionUsedAsync(BtbElse.ToString(), GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = BtbElse.ToString();
            }
            else
            {
                ApplicationService.IsTransactionUsedAsync(BtbElse.NoBtb, GlobalVar.User, mode);
                GlobalVar.CurrentTransaction = BtbElse.NoBtb;
            }
        }

        private void ApplicationService_IsTransactionUsedCompleted(object sender, IsTransactionUsedCompletedEventArgs e)
        {
            ApplicationService.IsTransactionUsedCompleted -= ApplicationService_IsTransactionUsedCompleted;
            IsUsed = e.Result;
            mode = (Mode) e.UserState;
            if (IsUsed)
            {
                MessageBox.Show("Transaksi sedang digunakan!");
                if (mode == Mode.Add) //If Add Mode
                {
                    mode = Mode.Idle;
                    Navigation.MyNavigation.Navigate(new Uri("/BtbElse/Index", UriKind.Relative));
                }
                else //Edit Mode just view Only
                {
                    IsEnabled = false;
                }
            }
        }

        private void ClearTransaksi(Mode mode)
        {
            ApplicationService.ClearTransactionCompleted += ApplicationService_ClearTransactionCompleted;
            if (mode == Mode.Add)
                ApplicationService.ClearTransactionAsync(BtbElse.ToString(), GlobalVar.User);
            else
                ApplicationService.ClearTransactionAsync(BtbElse.NoBtb, GlobalVar.User);
        }

        private void ApplicationService_ClearTransactionCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ApplicationService.ClearTransactionCompleted -= ApplicationService_ClearTransactionCompleted;
        }

        public void CloseStatus()
        {
            MessageBoxResult res = MessageBox.Show("Are You Sure Want to Close this Transaction ?", "Confirmation",
                                                   MessageBoxButton.OKCancel);
            if (res == MessageBoxResult.OK)
            {
                client.UpdateStatusCompleted += client_UpdateStatusCompleted;
                client.UpdateStatusAsync(BtbElse, Status.Close);
            }
        }

        private void client_UpdateStatusCompleted(object sender, AsyncCompletedEventArgs e)
        {
            client.UpdateStatusCompleted -= client_UpdateStatusCompleted;
            MessageBox.Show("Update Status finished!");
        }

        public bool CanLoadDetailFromFile(Object param)
        {
            return true;
        }

        public void LoadDetailFromFile(Object param)
        {
            var importHelper = new ImportHelper();
            IEnumerable<List<dynamic>> sourcesOld;
            importHelper.BrowseExcelFile(out sourcesOld);
          
            if (sourcesOld == null || sourcesOld.Count() == 0)
            {
                IEnumerable sources =
                    importHelper.LoadExcellFile(
                        importHelper.listSheetNames.FirstOrDefault());
                if (sources != null)
                {
                    foreach (dynamic data in sources)
                    {
                        var btbDetail = new BtbElseDetailDTO();
                        btbDetail.Items = new ObservableCollection<ItemDTO>();
                        var item = new ItemDTO { ItemId = data.K };
                        if (itemDicts.ContainsKey(item.ItemId))
                            item = itemDicts[item.ItemId];
                        btbDetail.Items.Add(item);
                        btbDetail.SatuanPacks = SatuanPacks;
                        btbDetail.SatuanUnits = SatuanUnits;
                        btbDetail.Warehouses = Warehouses;

                        btbDetail.NoBtb = BtbElse.NoBtb;
                        btbDetail.NoLog = data.A;
                        if (string.IsNullOrEmpty(btbDetail.NoLog)) continue;
                        btbDetail.NoBundle = int.Parse(data.B);
                        btbDetail.Description = data.C;
                        btbDetail.QtyPack = decimal.Parse(data.D);
                        //btbDetail.QtyUnit = decimal.Parse(data.E);
                        btbDetail.Price = decimal.Parse(data.F);
                        btbDetail.Panjang = decimal.Parse(data.G);
                        btbDetail.Lebar = decimal.Parse(data.H);
                        btbDetail.Tinggi = decimal.Parse(data.I);
                        btbDetail.KodeMasuk = data.J;
                        btbDetail.Item =
                            btbDetail.Items.FirstOrDefault(x => x.ItemId == data.K);
                        btbDetail.SatuanPack =
                            btbDetail.SatuanPacks.FirstOrDefault(
                                x => x.KodeSatuan == data.L);
                        btbDetail.SatuanUnit =
                            btbDetail.SatuanUnits.FirstOrDefault(
                                x => x.KodeSatuan == data.M);
                        btbDetail.Warehouse =
                            btbDetail.Warehouses.FirstOrDefault(
                                x => x.KodeWarehouse == data.N);
                        btbDetail.KodePallet = data.O;
                        GetQtyUnit(btbDetail);
                        btbDetail.QtyUnit = btbDetail.Item.IsRounded
                                                ? btbDetail.QtyUnit.Round(2,
                                                                          MidpointRounding
                                                                              .
                                                                              AwayFromZero)
                                                : btbDetail.QtyUnit.Round(4,
                                                                          MidpointRounding
                                                                              .
                                                                              AwayFromZero);
                        BtbElse.BtbDetails.Add(btbDetail);
                    }
                }
                   
            }
            else
            {
                int i = 0;
                foreach (var data in sourcesOld)
                {
                    if (i > 0)
                    {
                        var btbDetail = new BtbElseDetailDTO();
                        btbDetail.Items = new ObservableCollection<ItemDTO>();
                        var item = new ItemDTO {ItemId = data[10].ToString()};
                        if (itemDicts.ContainsKey(item.ItemId))
                            item = itemDicts[item.ItemId];
                        else
                            MessageBox.Show("ItemID " + item.ItemId +
                                            "tidak ada di Master Item!");


                        btbDetail.Items.Add(item);
                        btbDetail.SatuanPacks = SatuanPacks;
                        btbDetail.SatuanUnits = SatuanUnits;
                        btbDetail.Warehouses = Warehouses;

                        btbDetail.NoBtb = BtbElse.NoBtb;
                        btbDetail.NoLog = data[0].ToString();
                        if (string.IsNullOrEmpty(btbDetail.NoLog)) continue;
                        btbDetail.NoBundle = Convert.ToInt32(data[1]);
                        btbDetail.Description = data[2].ToString();
                        btbDetail.QtyPack = Convert.ToDecimal(data[3]);
                        //btbDetail.QtyUnit = decimal.Parse(data.E);
                        btbDetail.Price = Convert.ToDecimal(data[5]);
                        btbDetail.Panjang = Convert.ToDecimal(data[6]);
                        btbDetail.Lebar = Convert.ToDecimal(data[7]);
                        btbDetail.Tinggi = Convert.ToDecimal(data[8]);
                        btbDetail.KodeMasuk = data[9] != null ? (string) data[9].ToString() : string.Empty;
                        btbDetail.Item =
                            btbDetail.Items.FirstOrDefault(
                                x => x.ItemId == data[10].ToString());
                        btbDetail.SatuanPack =
                            btbDetail.SatuanPacks.FirstOrDefault(
                                x => x.KodeSatuan == data[11].ToString());
                        btbDetail.SatuanUnit =
                            btbDetail.SatuanUnits.FirstOrDefault(
                                x => x.KodeSatuan == data[12].ToString());
                        btbDetail.Warehouse =
                            btbDetail.Warehouses.FirstOrDefault(
                                x => x.KodeWarehouse == data[13].ToString());
                        btbDetail.KodePallet = data[14].ToString();
                        GetQtyUnit(btbDetail);
                        btbDetail.QtyUnit = btbDetail.Item.IsRounded
                                                ? btbDetail.QtyUnit.Round(2,
                                                                          MidpointRounding
                                                                              .
                                                                              AwayFromZero)
                                                : btbDetail.QtyUnit.Round(4,
                                                                          MidpointRounding
                                                                              .
                                                                              AwayFromZero);
                        BtbElse.BtbDetails.Add(btbDetail);
                    }

                    i++;
                }
            }
        }


        public void GetQtyUnit(BtbElseDetailDTO param)
        {
            Decimal pengali = 1;
            if (param.SatuanUnit != null && param.SatuanUnit.Pengali > 0)
                pengali = param.SatuanUnit.Pengali;
            param.QtyUnit = param.QtyPack*
                            (param.Panjang*param.Lebar*
                             param.Tinggi)/pengali;
        }

        public void GetItemList()
        {
            ItemClient.GetAllItemCompleted += ItemClient_GetAllItemCompleted;
            ItemClient.GetAllItemAsync();
        }

        private void ItemClient_GetAllItemCompleted(object sender, GetAllItemCompletedEventArgs e)
        {
            ItemClient.GetAllItemCompleted -= ItemClient_GetAllItemCompleted;
            itemDicts = e.Result.ToDictionary(x => x.ItemId);
        }

        public void CekSerialNumberExist(Object param)
        {
            if (mode != Mode.Edit)
            {
                invClient.GetInventoryCompleted += new EventHandler<GetInventoryCompletedEventArgs>(invClient_GetInventoryCompleted);
                invClient.GetInventoryAsync(param.ToString());
            }
        }

        void invClient_GetInventoryCompleted(object sender, GetInventoryCompletedEventArgs e)
        {
            invClient.GetInventoryCompleted -= new EventHandler<GetInventoryCompletedEventArgs>(invClient_GetInventoryCompleted);
            
            Deployment.Current.Dispatcher.BeginInvoke(() =>
                                                          {
                                                              if (e.Result != null && !string.IsNullOrEmpty(e.Result.SerialNumber))
                                                                  MessageBox.Show("SerialNumber " +
                                                                                  e.Result.SerialNumber + " sudah ada!");
                                                          });
        }
    }


    public class BtbElseWrapViewModel : ViewModelBase
    {
        private readonly ItemServicesClient ItemClient;
        private readonly PalletServicesClient PalletClient;
        private readonly SatuanServicesClient SatuanClient;
        private readonly WarehouseServicesClient WarehouseServicesClient;
        private readonly BtbElseServicesClient client;
        private BtbElseDetailDTO _BtbElseDetail;
        private ObservableCollection<ItemDTO> _Items;
        private ObservableCollection<PalletDTO> _Pallets;
        private ObservableCollection<SatuanDTO> _SatuanPacks;
        private ObservableCollection<SatuanDTO> _SatuanUnits;
        private ObservableCollection<WarehouseDTO> _Warehouses;


        public BtbElseWrapViewModel()
        {
            if (!DesignerProperties.IsInDesignTool)
            {
                EditCommand = new DelegateCommand(Edit, CanEditCommand);
                DeleteCommand = new DelegateCommand(Delete, CanDeleteCommand);
                client = new BtbElseServicesClient();
                ItemClient = new ItemServicesClient();
                PalletClient = new PalletServicesClient();
                SatuanClient = new SatuanServicesClient();
                WarehouseServicesClient = new WarehouseServicesClient();
              
                AddDetailCommand = new DelegateCommand(AddBtbElseDetail, CanAddDetailCommand);
                DeleteDetailCommand = new DelegateCommand(DeleteBtbElseDetail, CanDeleteDetailCommand);
                GetQtyUnitCommand = new DelegateCommand(GetQtyUnit, CanGetQtyUnit);

                if (BtbElseViewModel.mode == Mode.Add || BtbElseViewModel.mode == Mode.Edit)
                {
                }
            }
        }

        public BtbElseViewModel BtbElseViewModel { get; set; }


        public ICommand EditCommand { get; set; }
        public ICommand DeleteCommand { get; set; }
        public ICommand AddDetailCommand { get; set; }
        public ICommand DeleteDetailCommand { get; set; }
        public ICommand GetQtyUnitCommand { get; set; }


        public ObservableCollection<ItemDTO> Items
        {
            get { return _Items; }
            private set
            {
                if (Items == value) return;
                _Items = value;
                FirePropertyChanged("Items");
            }
        }


        public ObservableCollection<PalletDTO> Pallets
        {
            get { return _Pallets; }
            private set
            {
                if (Pallets == value) return;
                _Pallets = value;
                FirePropertyChanged("Pallets");
            }
        }


        public BtbElseDetailDTO BtbElseDetail
        {
            get { return _BtbElseDetail; }
            private set
            {
                if (BtbElseDetail == value) return;
                _BtbElseDetail = value;
                FirePropertyChanged("BtbElseDetail");
            }
        }

        public bool CanEditCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteCommand(Object param)
        {
            return true;
        }

        public bool CanAddDetailCommand(Object param)
        {
            return true;
        }

        public bool CanDeleteDetailCommand(Object param)
        {
            return true;
        }


        public void Edit(Object param)
        {
            BtbElseViewModel.mode = Mode.Edit;
            Navigation.MyNavigation.Navigate(new Uri("/BtbElse/frmAdd", UriKind.Relative));
            Navigation.Args = param;
        }

        public void Delete(Object param)
        {
            var deleteConfirmation = new DeleteConfirmation();
            deleteConfirmation.Show();
            EventAggregator.RegisterMessage("ApprovalSucceeded", (x) =>
                                                                     {
                                                                         deleteConfirmation.Close();
                                                                         client.DeleteCompleted +=
                                                                             client_DeleteCompleted;
                                                                         client.DeleteAsync((BtbElseDTO) param);
                                                                     });
        }

        private void client_DeleteCompleted(object sender, AsyncCompletedEventArgs e)
        {
            client.DeleteCompleted -= client_DeleteCompleted;
            if (e.Error == null)
                MessageBox.Show("Delete Success!");
            else
                MessageBox.Show(e.Error.Message);
            BtbElseViewModel.mode = Mode.Idle;
            var VM = new BtbElseViewModel();
        }

        public void AddBtbElseDetail(Object param)
        {
            if (param == null)
                param = BtbElseViewModel.BtbElse.BtbDetails[BtbElseViewModel.BtbElse.BtbDetails.Count - 1];
            var BtbElsedetail = param as BtbElseDetailDTO;
            BtbElseDetail = new BtbElseDetailDTO
                                {
                                    Items = BtbElsedetail.Items,
                                    Item =
                                        new ItemDTO
                                            {ItemId = BtbElsedetail.Item.ItemId, ItemName = BtbElsedetail.Item.ItemName,IsRounded = BtbElsedetail.Item.IsRounded},
                                    QtyPack = BtbElsedetail.QtyPack,
                                    SatuanPacks = BtbElsedetail.SatuanPacks,
                                    SatuanUnits = BtbElsedetail.SatuanUnits,
                                    Warehouses = BtbElsedetail.Warehouses,
                                    Warehouse = BtbElsedetail.Warehouse,
                                    Pallets = BtbElsedetail.Pallets,
                                    KodePallet = BtbElsedetail.KodePallet,
                                    SatuanPack = BtbElsedetail.SatuanPack,
                                    SatuanUnit = BtbElsedetail.SatuanUnit,
                                    Description = BtbElsedetail.Description,
                                    Price = BtbElsedetail.Price,
                                    KodeMasuk = BtbElsedetail.KodeMasuk
                                    
                                };
            BtbElseViewModel.BtbElse.BtbDetails.Add(BtbElseDetail);
        }

        public void DeleteBtbElseDetail(Object param)
        {
            var BtbElseDetail = (BtbElseDetailDTO) param;
            BtbElseDetail.NoBtb = BtbElseViewModel.BtbElse.NoBtb;

            if (BtbElseViewModel.BtbElse.BtbDetails.Count > 1)
            {
                if (param == null)
                {
                    int count = BtbElseViewModel.BtbElse.BtbDetails.Count;
                    BtbElseViewModel.BtbElse.BtbDetails.RemoveAt(count - 1);
                }
                else
                {
                    BtbElseViewModel.BtbElse.BtbDetails.Remove(BtbElseDetail);
                }
            }
        }

        public bool CanGetInventoryCommand(Object param)
        {
            return true;
        }

        public bool CanGetQtyUnit(Object param)
        {
            return true;
        }

        public void GetQtyUnit(Object param)
        {
            BtbElseDetail = (BtbElseDetailDTO) param;
            Decimal pengali = 1;
            if (BtbElseDetail.SatuanUnit != null && BtbElseDetail.SatuanUnit.Pengali > 0)
                pengali = BtbElseDetail.SatuanUnit.Pengali;
            BtbElseDetail.QtyUnit = BtbElseDetail.QtyPack*
                                    (BtbElseDetail.Panjang*BtbElseDetail.Lebar*
                                     BtbElseDetail.Tinggi)/pengali;

            BtbElseDetail.QtyUnit = BtbElseDetail.Item.IsRounded
                                        ? BtbElseDetail.QtyUnit.Round(2, MidpointRounding.AwayFromZero)
                                        : BtbElseDetail.QtyUnit.Round(4, MidpointRounding.AwayFromZero);
        }
    }

    public class BtbElseConverter : IValueConverter
    {
        #region IValueConverter Members

        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null)
            {
                return ((dynamic) value).NoBtb;
            }
            else
            {
                return string.Empty;
            }
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}